package it.univaq.mancoosi.injectors.systemconfiguration.managers.ubuntu;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.emf.ecore.util.EcoreUtil;

import it.univaq.mancoosi.injectors.systemconfiguration.managers.FileSystemManager;
import it.univaq.mancoosi.injectors.systemconfiguration.managers.MenuManager;
import it.univaq.mancoosi.injectors.systemconfiguration.utils.ProcessCommand;
import it.univaq.mancoosi.mancoosimm.File;
import it.univaq.mancoosi.mancoosimm.Menu;
import it.univaq.mancoosi.mancoosimm.MenuEntry;
import it.univaq.mancoosi.mancoosimm.MenuSection;
import it.univaq.mancoosi.mancoosimm.Rule;


public class UbuntuMenuManager extends MenuManager {
	
	protected Menu menu = factory.createMenu();
	
	public UbuntuMenuManager(){
		super();
	}

	public static MenuManager getInstance() {
		if (INSTANCE == null)
			INSTANCE = new UbuntuMenuManager();
		return INSTANCE;
	}

	@Override
	public void createMenuFromSystem() {
		syncEntryMap();
		syncSectionMap();
		
		if(UbuntuEnvironmentManager.getInstance().getEnvironment().getMenu() != null){
			this.menu.getEntries().addAll(UbuntuEnvironmentManager.getInstance().getEnvironment().getMenu().getEntries());
			this.menu.getSections().addAll(UbuntuEnvironmentManager.getInstance().getEnvironment().getMenu().getSections());
		}
		
		MenuEntry newMenuEntry;
		MenuSection newMenuSection;
		ArrayList<MenuEntry> menuEntries = new ArrayList<MenuEntry>();
		ArrayList<MenuSection> menuSection = new ArrayList<MenuSection>();
		String line;

		try {
			String[] cmd = {"/bin/sh","-c","ls --time-style=long-iso /usr/share/menu"};
//			String[] cmd = {"/bin/sh","-c","ls --time-style=long-iso /home/martina/prova"};
			BufferedReader input = ProcessCommand.getInstance().getResult(cmd);	
			
			while ((line = input.readLine()) != null) {
				if(!line.equals("README")){
					java.io.File file = new java.io.File("/usr/share/menu/"+line);
//					java.io.File file = new java.io.File("/home/martina/prova/"+line);

					if(file.exists()){
						File menuModelFile = UbuntuFileSystemManager.getInstance()
						.createFile(file.getPath());
						
						if (!existsEntry(file.getName())) {
							newMenuSection = createMenuSectionFromMenuEntry(file);
							menuSection.add(newMenuSection);
	
							newMenuEntry = factory.createMenuEntry();
							newMenuEntry.setMenu(this.menu);
							newMenuEntry.setName(line);
							newMenuEntry.setExecutable(menuModelFile);
							newMenuEntry.setParent(newMenuSection);
							menuEntries.add(newMenuEntry);
							this.entryMap.put(file.getName(), newMenuEntry);
							this.sectionMap.put(file.getName(), newMenuSection);
						}
					}
				}
			}
			
			this.menu.setEnv(UbuntuEnvironmentManager.getInstance().getEnvironment());
			this.menu.getEntries().addAll(menuEntries);
			this.menu.getSections().addAll(menuSection);
			
			input.close();

		} catch (Exception err) {
			err.printStackTrace();
		}
	}
	
	protected MenuSection createMenuSectionFromMenuEntry(java.io.File file){
		MenuSection menuSection = null;
		String section;
		String[] ss;
		boolean trovato = false;
		try{
			FileReader fileReader = new FileReader(file);
			BufferedReader fileBufferedReader = new BufferedReader(fileReader); 
			 
			while((section = fileBufferedReader.readLine()) != null && !trovato){
				
				if(section.contains("section")){
					trovato = true;
					menuSection = factory.createMenuSection();
					ss = section.split("section=\"");
					if(ss.length == 2){
						ss = ss[1].split("\"");
						section = ss[0];
					}
					menuSection.setName(section);
					menuSection.setEntryName(file.getName());
				}
			}
			if(menuSection != null){
				menuSection.setMenu(this.menu);
			}
			
		}catch(IOException e){
			e.printStackTrace();
		}
		
		return menuSection;
	}

	@Override
	public void synchronize() throws IOException {
		createMenuFromSystem();
		Iterator<MenuEntry> iterator = this.entryMap.values().iterator();
		while (iterator.hasNext()) {
			MenuEntry curr = iterator.next();
			if (isMissingEntryInTheSystem(curr.getName())) {
				this.entryMap.remove(curr);
				MenuSection currSection = this.sectionMap.get(curr.getName());
				this.sectionMap.remove(currSection);
				EcoreUtil.delete(curr);
				EcoreUtil.delete(currSection);
				UbuntuFileSystemManager.getInstance().deleteFile(curr.getExecutable());
			}else{
				//update menuSection for each menuEntry in the model because may be that it changed
				MenuEntry entryToModify = UbuntuEnvironmentManager.getInstance().getEnvironment().getMenu().getEntries().get(
						UbuntuEnvironmentManager.getInstance().getEnvironment().getMenu().getEntries().indexOf(curr));
				//delete section for this entry from the model and from the sectionMap
				EcoreUtil.delete(entryToModify.getParent());
				this.sectionMap.remove(entryToModify.getParent());
				
				//create the new section in case it has been modified
				java.io.File file = new java.io.File("/usr/share/menu/"+entryToModify.getName());
//				java.io.File file = new java.io.File("/home/martina/prova/"+entryToModify.getName());
				if(file.exists()){
					MenuSection section = createMenuSectionFromMenuEntry(file);
					//add it to the sectionMap
					this.sectionMap.put(file.getName(), section);
					//add it to the model
					UbuntuEnvironmentManager.getInstance().getEnvironment().getMenu().getSections().add(section);
					//set it like parent for the entry
					UbuntuEnvironmentManager.getInstance().getEnvironment().getMenu().getEntries().get(
							UbuntuEnvironmentManager.getInstance().getEnvironment().getMenu().getEntries().indexOf(curr)).setParent(section);
				}
			}
		}	
	}
	
	public boolean isMissingEntryInTheSystem (String entryName) {	
		if(UbuntuFileSystemManager.getInstance().getFile("/usr/share/menu/" + entryName) != null){
			return UbuntuFileSystemManager.getInstance().getFile("/usr/share/menu/" + entryName).isIsMissing();
		}else{
			return true;
		}
//		return UbuntuFileSystemManager.getInstance().getFile("/home/martina/prova/" + entryName).isIsMissing();

//		java.io.File file = new java.io.File("/usr/share/menu/" + entryName);
//		java.io.File file = new java.io.File("/home/martina/prova/" + entryName);
//		return file.exists();
	}

	@Override
	public Boolean existsEntry(String entryName) {
		return this.entryMap.containsKey(entryName);
	}

	@Override
	public Boolean existsSection(String sectionName) {
		return this.sectionMap.containsKey(sectionName);
	}

}
